#pragma once
#include "Header.h"
#include "CryptoDll/CryptoDll.h"

#ifndef _WIN64
    #pragma comment(lib, "..//Include//CryptoDll//x86//CryptoDll.lib")
#else
    #pragma comment(lib, "..//Include//CryptoDll//x64//CryptoDll.lib")
#endif

class CFile
{
private:
    HANDLE m_hFile;
    LPTSTR m_lpFileFullName;
    BOOL m_bNeedToClose;
    UINT m_OpenFlags;

private:
    enum _OPEN_FLAGS
    {
        //  access
        READ = 0x00,
        WRITE = 0x01,
        READ_WRITE = 0x02,

        //  shared
        EXCLUSIVE_ALL = 0x10,
        EXCLUSIVE_WRITE = 0x20,
        EXCLUSIVE_READ = 0x30,
        EXCLUSIVE_NONE = 0x40,

        //  create
        CREATE = 0x100, //  CREATE_ALWAYS
        OPEN = 0x200,   //  OPEN_EXISTING
        OPEN_IF = 0x300 //  OPEN_ALWAYS
    };

    enum _SEEK_POINTER_FROM
    {
        BEGIN = 0,
        CURRENT,
        END
    };

public:
    using OF = _OPEN_FLAGS;
    using SP = _SEEK_POINTER_FROM;

public:
    CFile();
    CFile(IN HANDLE hFile, IN UINT OpenFlags);
    CFile(IN LPCTSTR lpFileName, IN UINT OpenFlags);
    CFile(IN const CFile& File);
    virtual ~CFile();

protected:
    void InitMms();
    void ClearRs();
    void SetFilePathName(IN LPCTSTR lpFileName);
    void GetFilePathNameByHandle(IN HANDLE hFile);

public:
    operator HANDLE() const;
    CFile& operator=(const CFile& s);

public: //  operate
    BOOL Open(IN LPCTSTR lpFileName, IN UINT OpenFlags);
    void Close();
    BOOL Rename(IN LPCTSTR lpNewFileName);
    BOOL Delete();
    BOOL MoveTo(IN LPCTSTR lpNewFilePathName);
    BOOL CopyTo(IN LPCTSTR lpNewFilePathName, IN BOOL bOpenNew = FALSE, IN BOOL bOverWrite = FALSE);
    BOOL Read(IN PVOID lpBuff, IN DWORD dwNumberOfBytesToRead, OUT LPDWORD lpNumberOfBytesRead);
    BOOL Write(IN PVOID lpBuff, IN DWORD dwNumberOfBytesToWrite, OUT LPDWORD lpNumberOfBytesWritten, IN BOOL bTruncate = TRUE);
    BOOL Append(IN PVOID lpBuff, IN DWORD dwNumberOfBytesToWrite, OUT LPDWORD lpNumberOfBytesWritten);
    BOOL Flush();
    ULONGLONG Seek(IN LONGLONG MoveOffset, IN DWORD MoveFrom);
    ULONGLONG SeekToEnd();
    void SeekToBegin();
    void Truncate();
    void SetFileSize(IN ULONGLONG Size);
    BOOL SetHide(IN BOOL bHide = TRUE);
    BOOL SetReadOnly(IN BOOL bReadOnly = TRUE);
    BOOL EncryptByRc4(IN const unsigned char* user16key, IN LPCTSTR lpEncryptFilePath, IN BOOL bDelete = FALSE);
    BOOL DecryptByRc4(IN const unsigned char* user16key, IN LPCTSTR lpDecryptFilePath, IN BOOL bDelete = FALSE);
    BOOL EncryptByAes(IN const unsigned char* user128key, IN LPCTSTR lpEncryptFilePath, IN BOOL bDelete = FALSE);
    BOOL DecryptByAes(IN const unsigned char* user128key, IN LPCTSTR lpEncryptFilePath, IN BOOL bDelete = FALSE);

public: //  info
    ULONGLONG GetFileSize();
    LPCTSTR GetFileFullName();
    LPCTSTR GetFileName();
    BOOL GetFileTime(OUT PSYSTEMTIME lpCreateTime, OUT PSYSTEMTIME lpLastAccessTime, OUT PSYSTEMTIME lpLastWriteTime, OUT PSYSTEMTIME lpLastChangeTime);
};
